/*
 *  Copyright © 2018 - 2021 xulianqiang90@163.com. All Rights Reserved.
 */

package io.light.frame.dal.mybatis.generator.core.meta.visit;

import io.light.frame.dal.mybatis.generator.core.meta.visit.opt.MetaOperations;
import org.springframework.beans.factory.InitializingBean;

/**
 * Metadata accessor
 *
 * @author Ivan
 * @version 1.0.0
 * @date 2021-05-15 06:57
 */
public interface MetaAccessor extends InitializingBean {

    /**
     * Lookup jdbc template
     *
     * @return {@link DialectJdbcTemplate}
     */
    DialectJdbcTemplate lookupJdbcTemplate();

    /**
     * Do meta operations
     *
     * @param pipe meta operations pipeline
     * @param <T>  {@link MetaOperations}
     * @return touch result
     * @throws Exception operations error
     */
    default <T> T touch(Pipe<MetaOperations> pipe) throws Exception {
        return touch(null, pipe);
    }

    /**
     * Do meta operations
     *
     * @param pipe meta operations pipeline
     * @throws Exception operations error
     */
    default void touch(PipeWithoutResult<MetaOperations> pipe) throws Exception {
        touch(null, pipe);
    }

    /**
     * Do meta operations
     *
     * @param datasourceId datasource bean id
     * @param pipe         meta operations pipeline
     * @throws Exception operations error
     */
    default void touch(String datasourceId, PipeWithoutResult<MetaOperations> pipe) throws Exception {
        touch(datasourceId, (Pipe<MetaOperations>) pipe);
    }

    /**
     * Do meta operations
     *
     * @param datasourceId datasource bean id
     * @param pipe         meta operations pipeline
     * @param <T>          {@link MetaOperations}
     * @return touch result
     * @throws Exception operations error
     */
    <T> T touch(String datasourceId, Pipe<MetaOperations> pipe) throws Exception;


    interface Pipe<M extends MetaOperations> {
        Object accept(M t) throws Exception;
    }

    interface PipeWithoutResult<M extends MetaOperations> extends Pipe<M> {

        @Override
        default Object accept(M t) throws Exception {
            apply(t);
            return null;
        }

        void apply(M t) throws Exception;
    }
}